package cn.uncode.springcloud.starter.canary.ribbon.predicate;

import java.util.Map;

import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;

import cn.uncode.springcloud.starter.boot.app.AppInfo;
import cn.uncode.springcloud.starter.canary.ribbon.support.RibbonContextHolder;
import cn.uncode.springcloud.utils.obj.ObjectUtil;
import cn.uncode.springcloud.utils.string.StringUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * A default implementation of {@link DiscoveryEnabledServer} that matches the instance against the attributes
 * registered through
 *
 * @author Juny
 * @see DiscoveryEnabledPredicate
 */
@Slf4j
public class MetadataAwarePredicate extends DiscoveryEnabledPredicate {

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean apply(DiscoveryEnabledServer server) {
    	
    	//1、查看目标选择节点状态，是正常节点，还是灰度节点
    	String canaryFlag = null;
    	boolean canary = false;
    	final Map<String, String> metadata = server.getInstanceInfo().getMetadata();
    	if(null != metadata && metadata.size() > 0) {
    		canaryFlag = metadata.get(AppInfo.APPLICATION_VERSION_METADATA_KEY);
    	}
    	if(StringUtil.isNotBlank(canaryFlag)) {
    		canary = true;
    		log.info("该节点为灰度节点："+server.toString() + ", canaryFlag:" + canaryFlag);
    	}else {
    		log.info("该节点为正常节点："+server.toString());
    	}
    	//2、正常节点
    	if(!canary) {
        	//2.1、请求上下文变量为空，视为正常请求
            if (ObjectUtil.isEmpty(RibbonContextHolder.getCurrentContext())) {
                log.info("请求上下文中无灰度信息");
                return true;
            }else {
            	//2.2、请求上下文变量不为空，灰度服务列表中没有目标调用服务名称，说明只有正常节点
                if(!RibbonContextHolder.getCurrentContext().containsCanaryAppName(server.getInstanceInfo().getAppName())) {
                    return true;
                }else {//2.3、目标调用服务名称在灰度服务列表中，但目标调用节点是正常节点，需要重新选择
                	return false;
                }
            }
           
    	}else {//3、灰度节点
    		//3.1、请求上下文变量为空，视为正常请求
    		if (ObjectUtil.isEmpty(RibbonContextHolder.getCurrentContext())) {
                log.info("请求上下文中无灰度信息");
                //正常请求到了灰度节点，重新选择节点
                return false;
            }else {
            	//3.2、灰度请求，灰度节点，判断标识是否匹配
        		boolean match = RibbonContextHolder.getCurrentContext().getCanaryFlag().equals(canaryFlag);
        		//匹配成功
        		if(match) {
        			if (match) {
                    	log.warn("当前请求微灰度标识为：{}，目标调用服务名：{}， 匹配成功节点：{}", RibbonContextHolder.getCurrentContext().getCanaryFlag(), 
                    			server.getInstanceInfo().getAppName(), server.getInstanceInfo().getIPAddr()+":"+server.getInstanceInfo().getPort());
                    }
        			return true;
        		}else {
                    return false;
        		}
            }
    	}
    }
}
